﻿using System;
using System.Collections.Generic;
using System.Text;

using System.Globalization;
using System.Runtime.InteropServices;
using System.Collections;

namespace Sac.PiLink
{
    /// <summary>
    /// PI 函数操作类
    /// 作者：YZG
    /// 时间：2011-12-3
    /// </summary>
    public class PIAppLink
    {
        /// <summary>
        /// 连上指定PI数据库
        /// </summary>
        /// <param name="ServerName">服务器名</param>
        /// <param name="UserName">用户名</param>
        /// <param name="Password">密码</param>
        /// <returns></returns>
        public static int ConnectToServer(string serverName, string userName, string password)
        {
            int hwnd = 0, valid = 0;
            int i = PIApiLink.pilg_registerapp("piapi32.dll");
            return PIApiLink.pilg_login(hwnd, userName, serverName, password, out valid);
        }

        /// <summary>
        /// 断开所有PI数据库连接
        /// </summary>
        /// <returns></returns>
        public static int DisConnect()
        {
            return PIApiLink.pilg_disconnect();
        }

        /// <summary>
        /// 寻找TagName在PI数据库中对应的PointNum
        /// </summary>
        /// <param name="TagName"></param>
        /// <param name="PointNum"></param>
        /// <returns></returns>
        unsafe public static int FindPointNum(string tagName, out int pointNum)
        {
            byte[] btarr = Encoding.ASCII.GetBytes(tagName);
            int i;
            fixed (byte* bt = btarr)
            {
                i = PIApiLink.pipt_findpoint(bt, out pointNum);
            }
            return i;
        }

        /// <summary>
        /// 将时间字符串转换为PI系统时间戳
        /// </summary>
        /// <param name="TimeStr">时间字符串：dd-MMM-yy HH:mm:ss</param>
        /// <param name="TimeDate">返回的时间戳</param>
        /// <returns></returns>
        public static int GetPITime(string timeStr, out int timeStamp)
        {
            return PIApiLink.pitm_parsetime(timeStr, 0, out timeStamp);
        }

        /// <summary>
        /// 将C#时间对象转换为PI系统时间戳
        /// </summary>
        /// <param name="Time">DateTime时间类型</param>
        /// <param name="TimeStamp">返回的时间戳</param>
        /// <returns></returns>
        public static int GetPITime(DateTime dateTime, out int timeStamp)
        {
            return PIApiLink.pitm_parsetime(dateTime.ToString("dd-MMM-yy HH:mm:ss", CultureInfo.CreateSpecificCulture("en-US")), 0, out timeStamp);
        }

        /// <summary>
        /// 将PI时间戳转换为标准时间字符串
        /// </summary>
        /// <param name="TimeStr"></param>
        /// <param name="timestamp"></param>
        unsafe public static void GetSysTime(out string timeStr, int timeStamp)
        {
            byte[] timebyte = new byte[19];
            fixed (byte* timestring = timebyte)
            {
                PIApiLink.pitm_formtime(timeStamp, timestring, 19);
                timeStr = Encoding.ASCII.GetString(timebyte);
            }
            timeStr = DateTime.Parse(timeStr, CultureInfo.CreateSpecificCulture("en-US")).ToString("yyyy-MM-dd HH:mm:ss");
        }

        /// <summary>
        ///  将PI时间戳转换为C#时间对象
        /// </summary>
        /// <param name="date"></param>
        /// <param name="timestamp"></param>
        unsafe public static void GetSysTime(out DateTime date, int timeStamp)
        {
            byte[] timebyte = new byte[19];
            fixed (byte* timestring = timebyte)
            {
                PIApiLink.pitm_formtime(timeStamp, timestring, 19);
                date = DateTime.Parse(Encoding.UTF8.GetString(timebyte), CultureInfo.CreateSpecificCulture("en-US"));
            }
        }

        /// <summary>
        /// 获取Tag的数据类型,R (real, floating point), I (integer, whole numbers0-32767), or D (digital)
        /// </summary>
        /// <param name="pt"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static int GetPointType(int pt, out char type)
        {
            return PIApiLink.pipt_pointtype(pt, out type);
        }

        /// <summary>
        /// 获取浮点型Tag的当前值
        /// </summary>
        /// <param name="tagName"></param>
        /// <param name="rval"></param>
        /// <param name="istat"></param>
        /// <param name="timeStr"></param>
        /// <returns></returns>
        public static int GetCurValue(string tagName, out double rval, out int istat, out string timeStr)
        {
            int PointNum = 0;
            int ErrNo = FindPointNum(tagName, out PointNum);
            rval = -9999.99F;
            istat = 0;
            timeStr = "";
            if (ErrNo == 0)
            {
                int TimeDate = 0;
                float fval = 0.0f;
                ErrNo = PIApiLink.pisn_getsnapshot(PointNum, out fval, out istat, out TimeDate);
                rval = (double)fval;
                GetSysTime(out timeStr, TimeDate);
            }
            else
            {
                GetSysTime(out timeStr, 0);
            }
            return ErrNo;
        }

        /// <summary>
        /// 获取浮点型Tag的当前值
        /// </summary>
        /// <param name="tagName"></param>
        /// <param name="rval"></param>
        /// <param name="istat"></param>
        /// <param name="datetime"></param>
        /// <returns></returns>
        public static int GetCurValue(string tagName, out double rval, out int istat, out DateTime datetime)
        {
            string timeStr;
            int ErrNo = GetCurValue(tagName, out rval, out istat, out timeStr);
            datetime = DateTime.Parse(timeStr);
            return ErrNo;
        }

        /// <summary>
        /// 获取Tag的当前值
        /// </summary>
        /// <param name="tagName"></param>
        /// <param name="drval"></param>
        /// <param name="ival"></param>
        /// <param name="bval"></param>
        /// <param name="bsize"></param>
        /// <param name="istat"></param>
        /// <param name="flags"></param>
        /// <param name="timeStr"></param>
        /// <returns></returns>
        public static int GetCurValue(string tagName, out double drval, out int ival, out object bval,
            ref int bsize, out int istat, out int flags, out string timeStr)
        {
            int PointNum = 0;
            int ErrNo = FindPointNum(tagName, out PointNum);
            drval = -9999.99F; ival = -9999; bval = null; istat = 0; flags = 0; timeStr = "";
            if (ErrNo == 0)
            {
                PIApiLink.PITimeStamp TimeStampStruct;
                ErrNo = PIApiLink.pisn_getsnapshotx(PointNum, out drval, out ival, out bval, ref bsize, out istat, out flags, out TimeStampStruct);
                DateTime datetime = ConverPITimeToDateTime(TimeStampStruct);
                timeStr = datetime.ToString("yyyy-MM-dd HH:mm:ss");
            }
            return ErrNo;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="tagName"></param>
        /// <param name="drval"></param>
        /// <param name="ival"></param>
        /// <param name="bval"></param>
        /// <param name="bsize"></param>
        /// <param name="istat"></param>
        /// <param name="flags"></param>
        /// <param name="datetime"></param>
        /// <returns></returns>
        public static int GetCurValue(string tagName, out double drval, out int ival, out object bval,
            ref int bsize, out int istat, out int flags, out DateTime datetime)
        {
            int PointNum = 0;
            int ErrNo = FindPointNum(tagName, out PointNum);
            drval = -9999.99F; ival = -9999; bval = null; istat = 0; flags = 0;
            GetSysTime(out datetime, 0);
            if (ErrNo == 0)
            {
                PIApiLink.PITimeStamp TimeStampStruct;
                ErrNo = PIApiLink.pisn_getsnapshotx(PointNum, out drval, out ival, out bval, ref bsize, out istat, out flags, out TimeStampStruct);
                datetime = ConverPITimeToDateTime(TimeStampStruct);
            }
            return ErrNo;
        }

        /// <summary>
        /// 返回当前时刻最新的PI值
        /// </summary>
        /// <param name="tagName">点号</param>
        /// <param name="drval">返回的PI值</param>
        /// <param name="datetime">返回的PI值的时间，发生错误时候返回1900-1-1 00:00:00</param>
        /// <returns>错误代码</returns>
        public static int GetCurrentValue(string tagName, out double drval, out DateTime datetime)
        {
            int PointNum = 0;
            int ErrNo = FindPointNum(tagName, out PointNum);
            drval = -9999;
            int ival = -9999, bsize = 0, istat = 0, flags = 0;
            object bval = null;
            datetime = DateTime.Parse("1900-1-1 00:00:00");
            if (ErrNo == 0)
            {
                PIApiLink.PITimeStamp TimeStampStruct;
                ErrNo = PIApiLink.pisn_getsnapshotx(PointNum, out drval, out ival, out bval, ref bsize, out istat, out flags, out TimeStampStruct);
                datetime = ConverPITimeToDateTime(TimeStampStruct);
            }
            return ErrNo;
        }

        /// <summary>
        /// 获取指定时刻的历史值
        /// </summary>
        /// <param name="tagName">点号</param>
        /// <param name="mode">1:ARCVALUEBEFORE;2:ARCVALUEAFTER;3:ARCVALUEINTERP;4:ARCVALUECODE.</param>
        /// <param name="drval">返回的PI点值</param>
        /// <param name="datetime">PI点值的时刻</param>
        /// <returns>错误代码</returns>
        public static int GetHistoryValue(string tagName, int mode, out double drval, ref DateTime datetime)
        {
            int PointNum = 0;
            int ErrNo = FindPointNum(tagName, out PointNum);
            drval = 0.0;
            int ival = 0, istat = 0, flags = 0, bsize = 0;
            object bval = null;
            if (ErrNo == 0)
            {
                PIApiLink.PITimeStamp pits = ConverDateTimeToPITime(datetime);
                ErrNo = PIApiLink.piar_getarcvaluex(PointNum, mode, out drval, out ival, out bval, ref bsize, out istat, out flags, out pits);
                datetime = ConverPITimeToDateTime(pits);
            }
            return ErrNo;
        }

        /// <summary>
        /// 获取指定时刻（到秒）前一点的PI数据库中的历史值
        /// </summary>
        /// <param name="tagName">PI点号</param>
        /// <param name="drval">返回PI点值</param>
        /// <param name="datetime">PI点值的时间</param>
        /// <returns>错误代码</returns>
        public static int GetPreviousValue(string tagName, out double drval, ref DateTime datetime)
        {
            return GetHistoryValue(tagName, 1, out drval, ref datetime);
        }

        /// <summary>
        /// 获取指定时刻（到秒）的值（如果指定时刻没有值则返回指定时刻前一点的值）
        /// </summary>
        /// <param name="tagName">PI点号</param>
        /// <param name="drval">返回PI点值</param>
        /// <param name="datetime">PI点值的时间</param>
        /// <returns>错误代码</returns>
        public static int GetPreviousOrAssignValue(string tagName, out double drval, ref DateTime datetime)
        {
            datetime = datetime.AddSeconds(1);
            return GetHistoryValue(tagName, 1, out drval, ref datetime);
        }

        /// <summary>
        /// 获取指定时刻（到秒）后一点的PI数据库中的历史值
        /// </summary>
        /// <param name="tagName">PI点号</param>
        /// <param name="drval">返回PI点值</param>
        /// <param name="datetime">PI点值的时间</param>
        /// <returns>错误代码</returns>
        public static int GetAfterValue(string tagName, out double drval, ref DateTime datetime)
        {
            datetime = datetime.AddSeconds(1);
            return GetHistoryValue(tagName, 2, out drval, ref datetime);
        }

        /// <summary>
        /// 获取指定时刻（到秒）的值（如果指定时刻没有值返回指定时刻后一点的值）
        /// </summary>
        /// <param name="tagName">PI点号</param>
        /// <param name="drval">返回PI点值</param>
        /// <param name="datetime">PI点值的时间</param>
        /// <returns>错误代码</returns>
        public static int GetAfterOrAssignValue(string tagName, out double drval, ref DateTime datetime)
        {
            return GetHistoryValue(tagName, 2, out drval, ref datetime);
        }

        /// <summary>
        /// 获取指定时间范围内所有的值（不包括指定时刻）
        /// </summary>
        /// <param name="tagName">PI点号</param>
        /// <param name="dtStartTime">指定的开始时间</param>
        /// <param name="dtEndTime">指定的结束时间</param>
        /// <param name="dArrValues">返回指定时间内各点值的数组</param>
        /// <param name="dtArrTimes">返回指定时间内各点值的时间</param>
        /// <param name="count">返回获取的点值的数目</param>
        /// <returns>返回各点值的错误代码数组</returns>
        public static int[] GetInsideValues(string tagName, DateTime dtStartTime, DateTime dtEndTime,
            out double[] dArrValues, out DateTime[] dtArrTimes)
        {
            ArrayList arrErrNo = new ArrayList();
            ArrayList arrValues = new ArrayList();
            ArrayList arrTimes = new ArrayList();
            DateTime dtTemp = dtStartTime;
            while (dtTemp < dtEndTime)
            {
                double dValue = 0;
                int errNo = GetAfterValue(tagName, out dValue, ref dtTemp);
                arrErrNo.Add(errNo);
                if (errNo == 0 || errNo == -15010)
                {
                    arrValues.Add(dValue);
                    arrTimes.Add(dtTemp);
                }
            }
            int count = arrValues.Count - 1;
            arrErrNo.RemoveAt(count);
            arrValues.RemoveAt(count);
            arrTimes.RemoveAt(count);
            dArrValues = (double[])arrValues.ToArray(typeof(double));
            dtArrTimes = (DateTime[])arrTimes.ToArray(typeof(DateTime));
            return (int[])arrErrNo.ToArray(typeof(int));
        }

        /// <summary>
        /// 获取指定时间范围内所有的值（不包括指定时刻）
        /// </summary>
        /// <param name="tagName">PI点号</param>
        /// <param name="dtStartTime">指定的开始时间</param>
        /// <param name="dtEndTime">指定的结束时间</param>
        /// <param name="dArrValues">包含所有指定时间内值的ArrayList对象</param>
        /// <param name="dtArrTimes">包含所有指定时间内点值时间的ArrayList对象</param>
        /// <param name="count">返回获取的点值的数目</param>
        /// <returns>返回各点值的错误代码数组</returns>
        public static int[] GetInsideValues(string tagName, DateTime dtStartTime, DateTime dtEndTime,
            out ArrayList dArrValues, out ArrayList dtArrTimes, out int count)
        {
            ArrayList arrErrNo = new ArrayList();
            dArrValues = new ArrayList();
            dtArrTimes = new ArrayList();
            DateTime dtTemp = dtStartTime;
            if (dtEndTime > DateTime.Now)
                dtEndTime = DateTime.Now;
            while (dtTemp < dtEndTime)
            {
                double dValue = 0;
                int errNo = GetAfterValue(tagName, out dValue, ref dtTemp);
                arrErrNo.Add(errNo);
                if (errNo == 0 || errNo == -15010)
                {
                    dArrValues.Add(dValue);
                    dtArrTimes.Add(dtTemp);
                }
            }
            count = dArrValues.Count - 1;
            arrErrNo.RemoveAt(count);
            dArrValues.RemoveAt(count);
            dtArrTimes.RemoveAt(count);
            count = dArrValues.Count;
            return (int[])arrErrNo.ToArray(typeof(int));
        }

        /// <summary>
        /// 获取指定时间范围所有的值（包括指定时刻：如果指定起始时刻没有值则取其前一点值，如果指定结束时刻没有值则取其之后一点值）
        /// </summary>
        /// <param name="tagName">PI点号</param>
        /// <param name="dtStartTime">指定的开始时间</param>
        /// <param name="dtEndTime">指定的结束时间</param>
        /// <param name="dArrValues">返回指定时间内各点值的数组</param>
        /// <param name="dtArrTimes">返回指定时间内各点值的时间</param>
        /// <param name="count">返回获取的点值的数目</param>
        /// <returns>返回各点值的错误代码数组</returns>
        public static int[] GetOutSideValues(string tagName, DateTime dtStartTime, DateTime dtEndTime,
            out double[] dArrValues, out DateTime[] dtArrTimes, out int count)
        {
            ArrayList arrErrNo = new ArrayList();
            ArrayList arrValues = new ArrayList();
            ArrayList arrTimes = new ArrayList();
            DateTime dtTemp = dtStartTime;
            double firstValue;
            int firstErrNo = GetPreviousOrAssignValue(tagName, out firstValue, ref dtTemp);
            arrErrNo.Add(firstErrNo);
            arrValues.Add(firstValue);
            arrTimes.Add(dtTemp);
            if (dtEndTime > DateTime.Now)
                dtEndTime = DateTime.Now;
            while (dtTemp <= dtEndTime)
            {
                double dValue = 0;
                int errNo = GetAfterValue(tagName, out dValue, ref dtTemp);
                arrErrNo.Add(errNo);
                if (errNo == 0 || errNo == -15010)
                {
                    arrValues.Add(dValue);
                    arrTimes.Add(dtTemp);
                }
            }
            count = arrValues.Count;
            dArrValues = (double[])arrValues.ToArray(typeof(double));
            dtArrTimes = (DateTime[])arrTimes.ToArray(typeof(DateTime));
            return (int[])arrErrNo.ToArray(typeof(int));
        }

        /// <summary>
        /// 获取指定时间范围内所有的值（包括指定时间或者其之前或之后的点值）
        /// </summary>
        /// <param name="tagName">PI点号</param>
        /// <param name="dtStartTime">指定的开始时间</param>
        /// <param name="dtEndTime">指定的结束时间</param>
        /// <param name="dArrValues">包含所有指定时间内值的ArrayList对象</param>
        /// <param name="dtArrTimes">包含所有指定时间内点值时间的ArrayList对象</param>
        /// <param name="count">返回获取的点值的数目</param>
        /// <returns>返回各点值的错误代码数组</returns>
        public static int[] GetOutSideValues(string tagName, DateTime dtStartTime, DateTime dtEndTime,
            out ArrayList dArrValues, out ArrayList dtArrTimes, out int count)
        {
            ArrayList arrErrNo = new ArrayList();
            dArrValues = new ArrayList();
            dtArrTimes = new ArrayList();
            DateTime dtTemp = dtStartTime;
            double firstValue;
            int firstErrNo = GetPreviousValue(tagName, out firstValue, ref dtTemp);
            arrErrNo.Add(firstErrNo);
            dArrValues.Add(firstValue);
            dtArrTimes.Add(dtTemp);
            while (dtTemp <= dtEndTime)
            {
                double dValue = 0;
                int errNo = GetAfterValue(tagName, out dValue, ref dtTemp);
                arrErrNo.Add(errNo);
                if (errNo == 0 || errNo == -15010)
                {
                    dArrValues.Add(dValue);
                    dtArrTimes.Add(dtTemp);
                }
            }
            count = dArrValues.Count;
            return (int[])arrErrNo.ToArray(typeof(int));
        }

        /// <summary>
        /// 获取指定时间点（秒级）之后的历史值，如果当前时间有值，则返回当前时间点值；如果当前时间点没有值，则返回当前时间后一点值
        /// </summary>
        /// <param name="tagName"></param>
        /// <param name="drval"></param>
        /// <param name="ival"></param>
        /// <param name="bval"></param>
        /// <param name="bsize"></param>
        /// <param name="istat"></param>
        /// <param name="flags"></param>
        /// <param name="datetime"></param>
        /// <returns></returns>
        public static int GetNowOrAfterValue(string tagName, out double drval, out int ival, out object bval,
            ref int bsize, out int istat, out int flags, ref DateTime datetime)
        {
            int PointNum = 0;
            int ErrNo = FindPointNum(tagName, out PointNum);
            drval = 0.0; ival = 0; bval = null; istat = 0; flags = 0;
            if (ErrNo == 0)
            {
                datetime = datetime.AddSeconds(-1);
                PIApiLink.PITimeStamp pits = new PIApiLink.PITimeStamp();
                pits.Year = datetime.Year;
                pits.Month = datetime.Month;
                pits.Day = datetime.Day;
                pits.Hour = datetime.Hour;
                pits.Minute = datetime.Minute;
                pits.Second = Convert.ToDouble(datetime.Second);
                ErrNo = PIApiLink.piar_getarcvaluex(PointNum, 2, out drval, out ival, out bval, ref bsize, out istat, out flags, out pits);
                datetime = new DateTime(pits.Year, pits.Month, pits.Day, pits.Hour, pits.Minute, 0);
                datetime = datetime.AddSeconds(pits.Second);
            }
            return ErrNo;
        }

        /// <summary>
        /// 获取积分值
        /// </summary>
        /// <param name="tagName"></param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static int GetTotalValue(string tagName, ref DateTime startTime, ref DateTime endTime, out float value)
        {
            int ErrNo = 0, PointNum = 0;
            ErrNo = FindPointNum(tagName, out PointNum);
            int startTimeStemp = 0, endTimeStemp = 0;
            float pctgood = 0f;
            value = 0;
            if (ErrNo == 0)
            {
                ErrNo = GetPITime(startTime, out startTimeStemp);
                ErrNo = GetPITime(endTime, out endTimeStemp);
                if (ErrNo == 0)
                {

                    ErrNo = PIApiLink.piar_summary(PointNum, ref startTimeStemp, ref endTimeStemp, out value, out pctgood, 0);
                    GetSysTime(out startTime, startTimeStemp);
                    GetSysTime(out endTime, endTimeStemp);
                }
            }
            return ErrNo;
        }

        /// <summary>
        /// 获取指定时间内最小值
        /// </summary>
        /// <param name="tagName">点号</param>
        /// <param name="startTime">指定起始时间（程序结束后返回最小值点的时间）</param>
        /// <param name="endTime">指定截止时间</param>
        /// <param name="value">最小值</param>
        /// <returns>错误代码</returns>
        public static int GetMiniValue(string tagName, ref DateTime startTime, ref DateTime endTime, out float value)
        {
            int ErrNo = 0, PointNum = 0;
            ErrNo = FindPointNum(tagName, out PointNum);
            int startTimeStemp = 0, endTimeStemp = 0;
            float pctgood = 0f;
            value = 0;
            if (ErrNo == 0)
            {
                ErrNo = GetPITime(startTime, out startTimeStemp);
                ErrNo = GetPITime(endTime, out endTimeStemp);
                if (ErrNo == 0)
                {

                    ErrNo = PIApiLink.piar_summary(PointNum, ref startTimeStemp, ref endTimeStemp, out value, out pctgood, 1);
                    GetSysTime(out startTime, startTimeStemp);
                    GetSysTime(out endTime, endTimeStemp);
                }
            }
            return ErrNo;
        }

        /// <summary>
        ///  获取指定时间内最打值
        /// </summary>
        /// <param name="tagName">点号</param>
        /// <param name="startTime">指定起始时间（程序结束后返回最大值点的时间）</param>
        /// <param name="endTime">指定截止时间</param>
        /// <param name="value">最大值</param>
        /// <returns>错误代码</returns>
        public static int GetMaxValue(string tagName, ref DateTime startTime, ref DateTime endTime, out float value)
        {
            int ErrNo = 0, PointNum = 0;
            ErrNo = FindPointNum(tagName, out PointNum);
            int startTimeStemp = 0, endTimeStemp = 0;
            float pctgood = 0f;
            value = 0;
            if (ErrNo == 0)
            {
                ErrNo = GetPITime(startTime, out startTimeStemp);
                ErrNo = GetPITime(endTime, out endTimeStemp);
                if (ErrNo == 0)
                {

                    ErrNo = PIApiLink.piar_summary(PointNum, ref startTimeStemp, ref endTimeStemp, out value, out pctgood, 2);
                    GetSysTime(out startTime, startTimeStemp);
                    GetSysTime(out endTime, endTimeStemp);
                }
            }
            return ErrNo;
        }

        /// <summary>
        /// 获取STD值
        /// </summary>
        /// <param name="tagName"></param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static int GetStdeValue(string tagName, ref DateTime startTime, ref DateTime endTime, out float value)
        {
            int ErrNo = 0, PointNum = 0;
            ErrNo = FindPointNum(tagName, out PointNum);
            int startTimeStemp = 0, endTimeStemp = 0;
            float pctgood = 0f;
            value = 0;
            if (ErrNo == 0)
            {
                ErrNo = GetPITime(startTime, out startTimeStemp);
                ErrNo = GetPITime(endTime, out endTimeStemp);
                if (ErrNo == 0)
                {

                    ErrNo = PIApiLink.piar_summary(PointNum, ref startTimeStemp, ref endTimeStemp, out value, out pctgood, 3);
                    GetSysTime(out startTime, startTimeStemp);
                    GetSysTime(out endTime, endTimeStemp);
                }
            }
            return ErrNo;
        }

        /// <summary>
        /// 最大与最小值差值
        /// </summary>
        /// <param name="tagName"></param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static int GetRangeValue(string tagName, ref DateTime startTime, ref DateTime endTime, out float value)
        {
            int ErrNo = 0, PointNum = 0;
            ErrNo = FindPointNum(tagName, out PointNum);
            int startTimeStemp = 0, endTimeStemp = 0;
            float pctgood = 0f;
            value = 0;
            if (ErrNo == 0)
            {
                ErrNo = GetPITime(startTime, out startTimeStemp);
                ErrNo = GetPITime(endTime, out endTimeStemp);
                if (ErrNo == 0)
                {

                    ErrNo = PIApiLink.piar_summary(PointNum, ref startTimeStemp, ref endTimeStemp, out value, out pctgood, 4);
                    GetSysTime(out startTime, startTimeStemp);
                    GetSysTime(out endTime, endTimeStemp);
                }
            }
            return ErrNo;
        }

        /// <summary>
        /// 加权平均
        /// </summary>
        /// <param name="tagName"></param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static int GetAvgValue(string tagName, ref DateTime startTime, ref DateTime endTime, out float value)
        {
            int ErrNo = 0, PointNum = 0;
            ErrNo = FindPointNum(tagName, out PointNum);
            int startTimeStemp = 0, endTimeStemp = 0;
            float pctgood = 0f;
            value = 0;
            if (ErrNo == 0)
            {
                ErrNo = GetPITime(startTime, out startTimeStemp);
                ErrNo = GetPITime(endTime, out endTimeStemp);
                if (ErrNo == 0)
                {

                    ErrNo = PIApiLink.piar_summary(PointNum, ref startTimeStemp, ref endTimeStemp, out value, out pctgood, 5);
                    GetSysTime(out startTime, startTimeStemp);
                    GetSysTime(out endTime, endTimeStemp);
                }
            }
            return ErrNo;
        }

        /// <summary>
        /// 算术平均
        /// </summary>
        /// <param name="tagName"></param>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static int GetMeanValue(string tagName, ref DateTime startTime, ref DateTime endTime, out float value)
        {
            int ErrNo = 0, PointNum = 0;
            ErrNo = FindPointNum(tagName, out PointNum);
            int startTimeStemp = 0, endTimeStemp = 0;
            float pctgood = 0f;
            value = 0;
            if (ErrNo == 0)
            {
                ErrNo = GetPITime(startTime, out startTimeStemp);
                ErrNo = GetPITime(endTime, out endTimeStemp);
                if (ErrNo == 0)
                {

                    ErrNo = PIApiLink.piar_summary(PointNum, ref startTimeStemp, ref endTimeStemp, out value, out pctgood, 6);
                    GetSysTime(out startTime, startTimeStemp);
                    GetSysTime(out endTime, endTimeStemp);
                }
            }
            return ErrNo;
        }

        /// <summary>
        /// 删除历史值
        /// </summary>
        /// <param name="tagName">指定点号</param>
        /// <param name="datetime">指定时间点</param>
        /// <returns>操作的错误代码</returns>
        public static int DeleteHistoryValue(string tagName, DateTime datetime)
        {
            int ErrNo = 0;
            int PointNum = 0;
            ErrNo = FindPointNum(tagName, out PointNum);
            if (ErrNo == 0)
            {
                int timeStemp = 0;
                ErrNo = GetPITime(datetime, out timeStemp);
                if (ErrNo == 0)
                {
                    ErrNo = PIApiLink.piar_deletevalue(PointNum, timeStemp);
                }
            }
            return ErrNo;
        }

        /// <summary>
        /// 向数据库中写入DOUBLE点的数据值
        /// </summary>
        /// <param name="tagName">点号</param>
        /// <param name="value">值</param>
        /// <param name="datetime">时间</param>
        /// <returns></returns>
        public static int SetHistoryValue(string tagName, float value, DateTime datetime)
        {
            int ErrNo = 0, PointNum = 0;
            ErrNo = FindPointNum(tagName, out PointNum);
            if (ErrNo == 0)
            {
                int timeStemp = 0;
                ErrNo = GetPITime(datetime, out timeStemp);
                if (ErrNo == 0)
                {
                    ErrNo = PIApiLink.piar_putvalue(PointNum, value, 0, timeStemp, 1);
                }
            }
            return ErrNo;
        }

        /// <summary>
        /// 向数据库中写入INT点的数据值
        /// </summary>
        /// <param name="tagName"></param>
        /// <param name="value"></param>
        /// <param name="datetime"></param>
        /// <returns></returns>
        public static int SetHistoryValue(string tagName, int value, DateTime datetime)
        {
            int ErrNo = 0, PointNum = 0;
            ErrNo = FindPointNum(tagName, out PointNum);
            if (ErrNo == 0)
            {
                int timeStemp = 0;
                ErrNo = GetPITime(datetime, out timeStemp);
                if (ErrNo == 0)
                {
                    ErrNo = PIApiLink.piar_putvalue(PointNum, 0f, value, timeStemp, 1);
                }
            }
            return ErrNo;
        }

        /// <summary>
        /// 向PI数据库中写入double点数据
        /// </summary>
        /// <param name="tagName"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static int SetCurrentValue(string tagName, float value)
        {
            int ErrNo = 0, PointNum = 0;
            ErrNo = FindPointNum(tagName, out PointNum);
            int timeStemp = 0;
            if (ErrNo == 0)
            {
                if (ErrNo == 0)
                {
                    ErrNo = PIApiLink.pisn_putsnapshot(PointNum, value, 0, timeStemp);
                }
            }
            return ErrNo;
        }

        /// <summary>
        /// 向PI数据库中写入double点数据
        /// </summary>
        /// <param name="tagName"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static int SetCurrentValue(string tagName, int value)
        {
            int ErrNo = 0, PointNum = 0;
            ErrNo = FindPointNum(tagName, out PointNum);
            int timeStemp = 0;
            if (ErrNo == 0)
            {
                if (ErrNo == 0)
                {
                    ErrNo = PIApiLink.pisn_putsnapshot(PointNum, 0f, value, timeStemp);
                }
            }
            return ErrNo;
        }

        /// <summary>
        /// 将PI的时间结构转换为C#时间对象
        /// </summary>
        /// <param name="PITime"></param>
        /// <returns></returns>
        public static DateTime ConverPITimeToDateTime(PIApiLink.PITimeStamp PITime)
        {
            DateTime time = new DateTime(PITime.Year, PITime.Month, PITime.Day, PITime.Hour, PITime.Minute, 0);
            time = time.AddSeconds(PITime.Second);
            //Convert.ToInt32(Math.Floor(PITime.Second)));
            return time;
        }

        /// <summary>
        /// 将C#时间对象转换为PI的时间结构
        /// </summary>
        /// <param name="datetime"></param>
        /// <returns></returns>
        public static PIApiLink.PITimeStamp ConverDateTimeToPITime(DateTime datetime)
        {
            PIApiLink.PITimeStamp PITime = new PIApiLink.PITimeStamp();
            PITime.Year = datetime.Year;
            PITime.Month = datetime.Month;
            PITime.Day = datetime.Day;
            PITime.Hour = datetime.Hour;
            PITime.Minute = datetime.Minute;
            PITime.Second = Convert.ToDouble(datetime.Second) + datetime.Millisecond / 1000;
            return PITime;
        }
    }
}
